package edu.zut.main.thread;

public class ThreadTicket {

    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        SaleTicketThread saleTicketThread = new SaleTicketThread(ticket);
        SaleTicketThread saleTicketThread1 = new SaleTicketThread(ticket);
        SaleTicketThread saleTicketThread2 = new SaleTicketThread(ticket);
        new Thread(saleTicketThread, "小花").start();
        new Thread(saleTicketThread1, "小李子").start();
        new Thread(saleTicketThread2, "小张").start();
    }

}

//模拟多个窗口进行售票
class SaleTicketThread implements Runnable {

    private Ticket ticket;

    public SaleTicketThread(Ticket ticket) {
        this.ticket = ticket;
    }

    @Override
    public void run() {
        //售票操作
        while (true) {
            //利用同步代码块进行同步，保证ticket共享资源每次只能由一个线程操作，
            // 当然，也可以利用同步方法，将getTicketNum与saleTicket方法进行同步，原理一样
            synchronized (ticket) {
                if (ticket.getTicketNum() <= 0)
                    break;
                ticket.saleTicket();
            }
        }
    }
}

//利用同步方法解决共享余票的问题，即将线程执行此方法未结束前可能会因阻塞导致其他线程也获取到这个资源的方法进行加锁
// 同步方法本质上还是同步对象，因方法本身就是由对象调用的
class Ticket {
    //余票
    private int ticketNum = 10;

    //将获取余票数的方法进行同步，保证只能由一个线程获取资源
    public int getTicketNum() {
        return ticketNum;
    }

    //进行同步，保证售票操作只能由一个线程操作
    public void saleTicket() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "售出了第" + ticketNum + "张票");
        ticketNum--;
    }


}

